import { BaseService } from '../framework/base-service.js'
import net from 'net'
import iconv from 'iconv-lite'
import _ from 'lodash'

export default class BSSService extends BaseService {
  static metadata = {
    name: 'bss',
    dependencies: [],
    singleton: true
  }
  
  constructor() {
    super()
    this.socket = null
    this.buffer = Buffer.alloc(0)
    this.isConnected = false
    this.heartbeatTimer = null
    this.reconnectTimer = null
    this.reconnectAttempts = 0
    this.maxReconnectAttempts = 10
    this.reconnectDelay = 5000
  }
  
  async onInit() {
    // 设置协议映射
    this.income = this.config.get('biz.bss.protocol.income', {})
    this.sendto = this.config.get('biz.bss.protocol.sendto', {})
    this.calls = this.config.get('biz.bss.protocol.calls', {})
    
    this.logger.info('BSSService', '✅ BSS service initialized')
  }
  
  async onStart() {
    // 启动时连接BSS
    await this.connect()
  }
  
  async onStop() {
    this.disconnect()
  }
  
  registerRoutes(app) {
    // BSS连接状态API
    app.get('/api/bss/status', c => {
      return c.json({
        connected: this.isConnected,
        reconnectAttempts: this.reconnectAttempts,
        bufferedMessages: this.buffer.length
      })
    })
    
    // 手动发送BSS消息
    app.post('/api/bss/send', async c => {
      const { flag, data } = await c.req.json()
      
      if (!this.isConnected) {
        return c.json({ error: 'BSS not connected' }, 503)
      }
      
      try {
        this.send(flag, data)
        return c.json({ success: true })
      } catch (err) {
        return c.json({ error: err.message }, 500)
      }
    })
    
    // 手动触发重连
    app.post('/api/bss/reconnect', async c => {
      try {
        await this.reconnect()
        return c.json({ success: true })
      } catch (err) {
        return c.json({ error: err.message }, 500)
      }
    })
    
    return true
  }
  
  registerEventListeners(eventBus) {
    // 监听业务事件，转发到BSS
    eventBus.on('bss:send', ({ flag, data }) => {
      this.send(flag, data)
    })
    
    // 监听命令响应请求
    eventBus.on('bss:response', ({ command, data }) => {
      this.handleCommandResponse(command, data)
    })
  }
  
  registerScheduledTasks(scheduler) {
    // 注册心跳任务
    scheduler.registerTask('bss-heartbeat', {
      cron: '*/5 * * * * *',  // 每5秒
      handler: () => this.sendHeartbeat()
    })
    
    // 注册登录任务（年度执行）
    scheduler.registerTask('bss-signin', {
      cron: '0 0 0 1 1 *',  // 每年1月1日
      runOnInit: true,  // 启动时执行一次
      handler: () => this.sendSignin()
    })
  }
  
  async connect() {
    const host = this.config.get('biz.bss.host', '127.0.0.1')
    const port = this.config.get('biz.bss.port', 4000)
    
    return new Promise((resolve, reject) => {
      this.logger.info('BSSService', `Connecting to BSS server at ${host}:${port}...`)
      
      this.socket = net.connect(port, host)
      
      this.socket.on('connect', () => {
        this.logger.info('BSSService', `✅ Connected to BSS server at ${host}:${port}`)
        this.isConnected = true
        this.reconnectAttempts = 0
        
        // 立即发送登录消息
        this.sendSignin()
        
        resolve()
      })
      
      this.socket.on('data', data => this.handleData(data))
      
      this.socket.on('error', err => {
        this.logger.error('BSSService', 'BSS connection error:', { error: err.message })
        if (!this.isConnected) {
          reject(err)
        }
        this.scheduleReconnect()
      })
      
      this.socket.on('close', () => {
        this.logger.warn('BSSService', 'BSS connection closed')
        this.isConnected = false
        this.scheduleReconnect()
      })
      
      // 设置超时
      setTimeout(() => {
        if (!this.isConnected) {
          reject(new Error('BSS connection timeout'))
          this.scheduleReconnect()
        }
      }, 10000)
    })
  }
  
  disconnect() {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer)
      this.heartbeatTimer = null
    }
    
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer)
      this.reconnectTimer = null
    }
    
    if (this.socket) {
      this.socket.destroy()
      this.socket = null
    }
    
    this.isConnected = false
    this.logger.info('BSSService', 'BSS disconnected')
  }
  
  handleData(data) {
    // 将接收到的数据追加到缓冲区
    this.buffer = Buffer.concat([this.buffer, data])
    
    // 循环处理完整的消息
    while (this.buffer.length >= 8) {
      // 读取消息头
      const flag = this.buffer.readUInt16LE(0)
      const length = this.buffer.readUInt32LE(2)
      
      // 检查是否有完整的消息体
      if (this.buffer.length < length + 8) break
      
      // 提取消息体
      const body = this.buffer.slice(8, length + 8)
      this.buffer = this.buffer.slice(length + 8)
      
      // 解码消息（GBK编码）
      const message = iconv.decode(body, 'gbk')
      
      // 处理消息
      this.handleMessage(flag, message)
    }
  }
  
  handleMessage(flag, message) {
    const eventName = this.income[flag]
    
    if (!eventName) {
      this.logger.warn('BSSService', `Unknown BSS flag: ${flag}`)
      return
    }
    
    this.logger.debug('BSSService', `BSS message [${flag}]: ${eventName}`)
    
    try {
      const data = JSON.parse(message)
      
      // 触发事件
      this.eventBus.emit(`bss:${eventName}`, data)
      
      // 处理需要自动响应的命令
      if (eventName.startsWith('command:')) {
        this.handleCommand(eventName, data)
      }
      
      // 广播到WebSocket客户端
      if (this.wsManager) {
        this.wsManager.broadcast(`bss:${eventName}`, data)
      }
    } catch (err) {
      this.logger.error('BSSService', 'Failed to parse BSS message:', { 
        error: err.message,
        flag,
        message 
      })
    }
  }
  
  handleCommand(command, data) {
    // 查找对应的响应映射
    const callMapping = _(this.calls).find((value, key) => {
      const [cmdName] = value.split('>')
      return command.includes(cmdName)
    })
    
    if (callMapping) {
      const [, responseEvent] = callMapping.split('>')
      this.handleCommandResponse(command, data, responseEvent)
      return
    }
    
    // 默认响应处理
    const cmdName = command.split(':')[1]
    const feedbackEvent = `feedback:${cmdName}`
    const feedbackFlag = this.sendto[feedbackEvent]
    
    if (feedbackFlag) {
      // 生成并发送响应
      const response = this.generateResponse(cmdName, data)
      this.send(parseInt(feedbackFlag), response)
    }
  }
  
  handleCommandResponse(command, data, responseEvent) {
    const cmdName = command.split(':')[1]
    const feedbackEvent = responseEvent || `feedback:${cmdName}`
    const feedbackFlag = this.sendto[feedbackEvent]
    
    if (!feedbackFlag) {
      this.logger.warn('BSSService', `No feedback mapping for command: ${command}`)
      return
    }
    
    // 生成响应数据
    const response = this.generateResponse(cmdName, data)
    
    // 发送响应
    this.send(parseInt(feedbackFlag), response)
    
    this.logger.debug('BSSService', `Sent response for ${command} with flag ${feedbackFlag}`)
  }
  
  generateResponse(command, data) {
    // 根据不同的命令生成相应的响应数据
    const responses = {
      'address': () => ({
        status: 'success',
        address: '模拟地址响应',
        ...data
      }),
      
      'coordination': () => ({
        status: 'success',
        x: data.x || 120.123456,
        y: data.y || 31.123456
      }),
      
      'carLocation': () => ({
        status: 'success',
        carId: data.carId,
        location: {
          x: 120.123456,
          y: 31.123456,
          speed: 0,
          direction: 0
        }
      }),
      
      'dispatch': () => ({
        status: 'success',
        taskId: data.taskId,
        carId: data.carId,
        result: 'dispatched'
      }),
      
      'Gw_OneKeyEssort': () => ({
        status: 'success',
        sorted: true,
        result: []
      })
    }
    
    const responseGenerator = responses[command]
    if (responseGenerator) {
      return responseGenerator()
    }
    
    // 默认响应
    return {
      status: 'success',
      command,
      timestamp: Date.now(),
      ...data
    }
  }
  
  send(flag, data) {
    if (!this.isConnected || !this.socket) {
      this.logger.warn('BSSService', 'Cannot send message: BSS not connected')
      return
    }
    
    try {
      // 将数据转换为JSON字符串
      const message = typeof data === 'string' ? data : JSON.stringify(data)
      
      // 编码为GBK
      const body = iconv.encode(message, 'gbk')
      
      // 构建消息头（8字节）
      const header = Buffer.alloc(8)
      header.writeUInt16LE(flag, 0)  // 标志位（2字节）
      header.writeUInt32LE(body.length, 2)  // 消息长度（4字节）
      // 位置6-7为保留字段（2字节）
      
      // 发送完整消息
      const packet = Buffer.concat([header, body])
      this.socket.write(packet)
      
      this.logger.debug('BSSService', `Sent message with flag ${flag}:`, data)
    } catch (err) {
      this.logger.error('BSSService', 'Failed to send BSS message:', { error: err.message })
    }
  }
  
  sendHeartbeat() {
    if (!this.isConnected) return
    
    const flag = parseInt(this.sendto['feedback:heartbeat'] || 1000)
    const data = { ID: '001' }
    
    this.send(flag, data)
    this.logger.debug('BSSService', 'Sent heartbeat')
  }
  
  sendSignin() {
    if (!this.isConnected) return
    
    const flag = parseInt(this.sendto['feedback:signin'] || 1001)
    const data = {
      ID: '001',
      Pwd: '',
      Type: 'GIS',
      Name: 'ZITMapX'
    }
    
    this.send(flag, data)
    this.logger.info('BSSService', 'Sent signin message')
  }
  
  scheduleReconnect() {
    if (this.reconnectTimer) return
    
    if (this.reconnectAttempts >= this.maxReconnectAttempts) {
      this.logger.error('BSSService', `Max reconnection attempts (${this.maxReconnectAttempts}) reached`)
      return
    }
    
    this.reconnectAttempts++
    const delay = this.reconnectDelay * Math.min(this.reconnectAttempts, 5)
    
    this.logger.info('BSSService', `Scheduling reconnect attempt ${this.reconnectAttempts} in ${delay}ms`)
    
    this.reconnectTimer = setTimeout(() => {
      this.reconnectTimer = null
      this.reconnect()
    }, delay)
  }
  
  async reconnect() {
    this.disconnect()
    
    try {
      await this.connect()
      this.logger.info('BSSService', 'Reconnected successfully')
    } catch (err) {
      this.logger.error('BSSService', 'Reconnection failed:', { error: err.message })
      this.scheduleReconnect()
    }
  }
}